/*
 * @Description: 矩形树图
 * @Author: zy
 * @Date: 2020-10-25 13:41:28
 * @LastEditors: zy
 * @LastEditTime: 2020-10-25 20:31:22
 */
import * as d3 from 'd3'
export class TreeMapChart {
    chart = {}
    data = []
    divId = ''
    sum = ''
    color = d3.scaleOrdinal(d3.schemeCategory20c)

    constructor (divId) {
      this.divId = divId
      this.initChart()
    }

    draw () {
      this.initLayout()
      this.drawNode()
    }

    initChart () {
      this.chart.padding = {
        left: 20,
        right: 50,
        top: 50,
        bottom: 20
      }
      this.chart.divHeight = document.getElementById(this.divId).offsetHeight -
          this.chart.padding.top -
          this.chart.padding.bottom
      this.chart.divWidth = document.getElementById(this.divId).offsetWidth -
          this.chart.padding.left -
          this.chart.padding.right

      this.chart.svg = d3
        .select('#' + this.divId)
        .append('svg')
        .attr('width', this.chart.divWidth +
            this.chart.padding.left +
            this.chart.padding.right
        )
        .attr('height', this.chart.divHeight +
            this.chart.padding.top +
            this.chart.padding.bottom
        )
        .attr('class', 'svg_chart')
    }

    initLayout () {
      let data = JSON.parse(JSON.stringify(this.data))
      const value = this.sum === 'count' ? (d) => { return d.size ? 1 : 0 } : (d) => { return d.size }

      const treemap = d3.treemap()
        .size([this.chart.divWidth, this.chart.divHeight])

      const root = d3.hierarchy(data, d => d.children)
        .sum(value)

      this.data = treemap(root)

      this.chart.svg.append('g')
        .attr('class', 'nodes')
        .attr('transform', 'translate(' + this.chart.padding.left + ',' + this.chart.padding.top + ')')
    }

    drawNode () {
      let nodes = this.chart.svg.select('.nodes')
        .selectAll('.node')
        .data(this.data.leaves(), d => {
          return d.data.name
        }) // descendants 与 leaves 一样

      nodes.select('rect')
        .transition()
        .duration(1500)
        .attr('x', d => d.x0)
        .attr('y', d => d.y0)
        .attr('width', d => Math.max(0, d.x1 - d.x0))
        .attr('height', d => Math.max(0, d.y1 - d.y0))

      nodes.select('text')
        .transition()
        .duration(1500)
        .attr('x', d => d.x0)
        .attr('y', d => d.y0 + 12)

      let nodeEnter = nodes.enter()
        .append('g')
        .attr('class', 'node')

      nodeEnter.append('rect')
        .attr('x', d => d.x0)
        .attr('y', d => d.y0)
        .attr('width', d => Math.max(0, d.x1 - d.x0))
        .attr('height', d => Math.max(0, d.y1 - d.y0))
        .style('fill', d => this.color(d.parent.data.name))
        .style('stroke', 'white')

      nodeEnter.append('text')
        .attr('x', d => d.x0)
        .attr('y', d => d.y0 + 12)
        .text(d => d.data.name)
        .style('font-size', 12)

      let nodeExit = nodes.exit()
        .transition()
        .duration(750)
        .remove()

      nodeExit.select('rect')
        .attr('width', 0)
        .attr('height', 0)
    }
}
